package com.core.indexer;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.Map;

public class MinHeap {

	private static MinHeap mInstance = null;
	private ArrayList<IndexData.DocList> result;
	private ArrayList<IndexData.DocList> sortedResult;
	
	public static MinHeap Get()
	{
		if (mInstance == null)
			mInstance = new MinHeap();
		
		return mInstance;
	}
	
	public ArrayList<IndexData.DocList> HeapifyList(Map<String, Double> docList, int nCount)
	{
		if(nCount <= 0)
			return null;
		
		if(nCount == 1)
		{
			String tempDocNo = "";
			double tempDocScore = 0;
			
			for(String key : docList.keySet())
			{
				if(docList.get(key) > tempDocScore)
				{
					tempDocNo = key;
					tempDocScore = docList.get(key);
				}
			}
			
			sortedResult.add(IndexData.Get().new DocList(tempDocNo, tempDocScore));
			return sortedResult;
		}
		
		Iterator<Map.Entry<String, Double>> it = docList.entrySet().iterator();
		while(it.hasNext())
		{
			Map.Entry<String, Double> entry = it.next();
			result.add(IndexData.Get().new DocList(entry.getKey(), entry.getValue()));
			it.remove();
			if(result.size() >= nCount)
				break;
		}

		for(int i = (int)Math.floor((result.size() - 1)/2) ; i >= 0; i--)
		{
			Heapify(i);
		}
		
		
		if(docList.isEmpty())
		{
			ReversAndFineSort();
			return sortedResult;
		}
			
		for(String key : docList.keySet())
		{
			if(docList.get(key) > result.get(0).DocScore)
			{
				result.set(0, IndexData.Get().new DocList(key, docList.get(key)));
				for(int i = (int)Math.floor((result.size() - 1)/2) ; i >= 0; i--)
				{
					Heapify(i);
				}
			}
		}
				
		ReversAndFineSort();
		
		return sortedResult;
	}
	
	private void Heapify(int nPosition)
	{
		int child_pos = 2*nPosition + 1;
		while(child_pos < result.size())
		{
			
			if((child_pos < result.size()) && (child_pos + 1 < result.size()) && (result.get(child_pos).DocScore > result.get(child_pos + 1).DocScore))
			{
				child_pos++;
			}
			
			if(result.get(nPosition).DocScore <= result.get(child_pos).DocScore)
				break;
			else
			{
				Swap(result, nPosition, child_pos);
				nPosition = child_pos;
				child_pos = 2*nPosition + 1;
			}
		}
	}
	
	private void Swap(ArrayList<IndexData.DocList> list, int nPos1, int nPos2)
	{
		IndexData.DocList tempDoc = list.get(nPos1);
		list.set(nPos1, list.get(nPos2));
		list.set(nPos2, tempDoc);
	}
	
	private void ReversAndFineSort()
	{
		sortedResult.clear();
		while(result.size() > 0)
		{
			Swap(result, 0, result.size() - 1);
			IndexData.DocList doc = result.remove(result.size() - 1);
			sortedResult.add(0, doc);
			for(int i = (int)Math.floor((result.size() - 1)/2) ; i >= 0; i--)
			{
				Heapify(i);
			}
		}
		
	}
	
	private MinHeap()
	{
		result = new ArrayList<IndexData.DocList>();
		sortedResult = new ArrayList<IndexData.DocList>();
	}
}
